// 给定一个单词数组和一个长度 maxWidth，重新排版单词，使其成为每行恰好有 maxWidth 个字符，且左右两端对齐的文本。

// 你应该使用“贪心算法”来放置给定的单词；也就是说，尽可能多地往每行中放置单词。必要时可用空格 ' ' 填充，使得每行恰好有 maxWidth 个字符。

// 要求尽可能均匀分配单词间的空格数量。如果某一行单词间的空格不能均匀分配，则左侧放置的空格数要多于右侧的空格数。

// 文本的最后一行应为左对齐，且单词之间不插入额外的空格。

// 说明:

// 单词是指由非空格字符组成的字符序列。
// 每个单词的长度大于 0，小于等于 maxWidth。
// 输入单词数组 words 至少包含一个单词。
// 示例:

// 输入:
// words = ["This", "is", "an", "example", "of", "text", "justification."]
// maxWidth = 16
// 输出:
// [
//    "This    is    an",
//    "example  of text",
//    "justification.  "
// ]
// 示例 2:

// 输入:
// words = ["What","must","be","acknowledgment","shall","be"]
// maxWidth = 16
// 输出:
// [
//   "What   must   be",
//   "acknowledgment  ",
//   "shall be        "
// ]
// 解释: 注意最后一行的格式应为 "shall be    " 而不是 "shall     be",
//      因为最后一行应为左对齐，而不是左右两端对齐。       
//      第二行同样为左对齐，这是因为这行只包含一个单词。
// 示例 3:

// 输入:
// words = ["Science","is","what","we","understand","well","enough","to","explain",
//          "to","a","computer.","Art","is","everything","else","we","do"]
// maxWidth = 20
// 输出:
// [
//   "Science  is  what we",
//   "understand      well",
//   "enough to explain to",
//   "a  computer.  Art is",
//   "everything  else  we",
//   "do                  "
// ]

#include "../stdc++.h"

class Solution {
public:
    vector<string> fullJustify(vector<string>& words, int maxWidth) {
        vector<string> res{};
        int i{0};
        int n = words.size();
        while (i < n) {
            int j{i}; // 当前行所能容纳的最后一个单词的下标
            int len{0}; // 当前行所有单词长度和
            while (j < n && len + words[j].size() + j - i <= maxWidth) {
                len += words[j++].size(); 
            }
            string out{}; // 当前行输出字符串
            int space = maxWidth - len; // 空格数
            for (int k{i}; k < j; ++k) {
                out += words[k];
                if (space > 0) {
                    int tmp{};
                    if (j == n) { // 当前行是最后一行
                        if (j - k == 1) // 最后一个单词
                            tmp = space;
                        else tmp = 1; // 不是最后一个单词，每个后面只有一个空格
                    } else { // 当前行后面还有单词
                        if (j - k - 1 > 0) {
                            if (space % (j - k - 1) == 0)
                                tmp = space / (j - k - 1);
                            else tmp = space / (j - k - 1) + 1;
                        } else tmp = space;
                    }
                    out.append(tmp, ' ');
                    space -= tmp;
                }
            }
            res.push_back(out);
            i = j;
        }
        return res;
    }
};

class Solution {
private:
    // blank 返回长度为 n 的由空格组成的字符串
    string blank(int n) {
        return string(n, ' ');
    }
    // join 返回用 sep 拼接 [left, right) 范围内的 words 组成的字符串
    string join(vector<string>& words, int left, int right, string sep) {
        string s = words[left];
        for (int i{left + 1}; i < right; ++i) {
            s += sep + words[i];
        }
        return s;
    }
public:
    vector<string> fullJustify(vector<string>& words, int maxWidth) {
        vector<string> res;
        int right{0};
        int n = words.size();
        while (true) {
            int left{right}; // 当前行的第一个单词在words的位置
            int sumLen{0}; // 统计这一行单词长度之和
            // 循环确定当前行可以放多少个单词，注意单词之间应至少有一个空格
            while (right < n && sumLen + words[right].length() + right - left <= maxWidth) {
                sumLen += words[right++].length();
            }
            // 当前行是最后一行：单词左对齐，且单词之间应只有一个空格，在行末填充剩余空格
            if (right == n) {
                string s = join(words, left, n, " ");
                res.emplace_back(s + blank(maxWidth - s.length()));
                return res;
            }

            int numWords = right - left;
            int numSpaces = maxWidth - sumLen;
            // 当前行只有一个单词：该单词左对齐，在行末填充剩余空格
            if (numWords == 1) {
                res.emplace_back(words[left] + blank(numSpaces));
                continue;
            }
            // 当前行不止一个单词
            int avgSpaces = numSpaces / (numWords - 1);
            int extraSpaces = numSpaces % (numWords - 1);
            string s1 = join(words, left, left + extraSpaces + 1, blank(avgSpaces + 1)); // 拼接额外一个空格的单词
            string s2 = join(words, left + extraSpaces + 1, right, blank(avgSpaces)); // 拼接其余单词
            res.emplace_back(s1 + blank(avgSpaces) + s2);
        }
        return res;
    }
};